﻿/*************************************************************************************
 * 工    具：  HK_GlobalSetting
 * 
 * 描    述：  HKTools 工具全局设置
 * 
 * 版    本：  V1.3
 * 作    者：  京产肠饭
 * 
 * 创    建：  2021/08/30  V1.0
 * 
 * 更    新：  2024/10/06  V1.1
 *            1.代码优化；优化代码，减少/合并重复冗余的部分，提高代码的可维护性
 *            2.代码优化：减少字符串的使用(减少硬编码)，如使用nameof(xxx)
 *            3.功能优化：合并 HKTools 框架设置功能
 *            
 *            2024/10/07  V1.2
 *            1.功能优化：优化 HK_ArchitectureProvider 框架初始化的时机，框架调用时进行初始化，防止初始化时机错误导致的OnInit异常
 *
 *            2024/10/07  V1.3
 *            1.功能优化：重新绘制 HKTools 全局设置窗口
 * 
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using QFramework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace HKTools
{
    /// <summary>  
    /// HKTools 的 工具信息类，封装了工具的基本信息和状态管理  
    /// </summary>
    class HK_ToolInfo
    {
        // 界面显示的工具名称
        public string DisplayName;

        // 用于 EditorPrefs 存储和获取状态的键名
        string PrefsKey;

        // 工具当前状态（启用或禁用）
        public bool State
        {
            get
            {
                // 从 EditorPrefs 中获取工具的启用状态，默认值为 true（启用）
                return EditorPrefs.GetBool(PrefsKey, true);
            }
            set
            {
                // 获取当前状态
                bool curState = EditorPrefs.GetBool(PrefsKey, true);

                // 如果状态发生变化，更新状态并触发回调
                if (curState != value)
                {
                    EditorPrefs.SetBool(PrefsKey, value);
                    ChangeStateAction?.Invoke(value);
                }
            }
        }
        // 状态改变时的回调函数
        public Action<bool> ChangeStateAction;

        // 构造函数，初始化工具信息
        public HK_ToolInfo(string displayName, string prefsKey, Action<bool> changeStateAction)
        {
            DisplayName = displayName;
            PrefsKey = prefsKey;
            ChangeStateAction = changeStateAction;
        }
    }

    /// <summary>
    /// 全局设置窗口类
    /// </summary>
    public class HK_GlobalSetting : EditorWindow
    {
        string[] architectureTypeNames;
        Type[] architectureTypes;
        int selectedIndex = 0;

        // 获取需要修改的代码文件路径  
        string scriptPath = "Assets/HKTools/GlobalSettings/HK_ArchitectureProvider.cs";

        // 工具信息列表，存储所有工具的配置信息
        static List<HK_ToolInfo> tools = new List<HK_ToolInfo>();

        [InitializeOnLoadMethod]
        static void InitToolsState()
        {
            // 初始化工具信息列表
            tools.Clear();

            tools.Add(new HK_ToolInfo(
                "是否启用 SmartCopy（智能复制工具）",
                nameof(HK_SmartCopy),
                curState =>
                {
                    HK_SmartCopy.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 MakeGroup（打组工具）",
                nameof(HK_MakeGroup),
                curState =>
                {
                    HK_MakeGroup.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 HierarchyPro",
                nameof(HK_HierarchyPro),
                curState =>
                {
                    HK_HierarchyPro.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 ProjectPro",
                nameof(HK_ProjectPro),
                curState =>
                {
                    HK_ProjectPro.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 ScenePro",
                nameof(HK_ScenePro),
                curState =>
                {
                    HK_ScenePro.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 AutoSwitchToUTF8",
                nameof(HK_AutoSwitchToUTF8),
                curState =>
                {
                    HK_AutoSwitchToUTF8.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 ModelImporter",
                nameof(HK_ModelImporter),
                curState =>
                {
                    HK_ModelImporter.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 NormalMapImporter",
                nameof(HK_NormalMapImporter),
                curState =>
                {
                    HK_NormalMapImporter.ChangeState(curState);
                }
            ));

            tools.Add(new HK_ToolInfo(
                "是否启用 UGUIElementCustomize",
                nameof(HK_UGUIElementCustomize),
                curState =>
                {
                    HK_UGUIElementCustomize.ChangeState(curState);
                }
            ));

            // 初始化时，调用每个工具的状态改变方法，以确保工具状态与保存的偏好设置一致  
            foreach (var tool in tools)
            {
                tool.ChangeStateAction?.Invoke(tool.State);
            }
        }

        [MenuItem("HKTools/GlobalSettings...", priority = HK_MenuPriority.HK_GlobalSetting)]
        static void ShowSettingWindow()
        {
            EditorWindow settingWindow = GetWindow<HK_GlobalSetting>("HKTools 全局设置");
            settingWindow.minSize = new Vector2(512, 460);
            settingWindow.maxSize = new Vector2(512, 530);
            settingWindow.Show();
        }

        void OnEnable()
        {
            FindAllArchitectureTypes();
            SetSelectedIndexToCurrentArchitecture();
        }

        void OnGUI()
        {
            GUILayout.Space(5);

            // 加载并显示图片
            Texture2D loadedImage = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/HKTools/GlobalSettings/Editor/HKToolsLogo.png");

            if (loadedImage != null)
            {
                GUILayout.Label(loadedImage, GUILayout.Width(512), GUILayout.Height(115));
            }
            else
            {
                EditorGUILayout.HelpBox("未能加载图片，请检查路径是否正确。", MessageType.Warning);
            }
            GUILayout.Space(5);

            GUIStyle customLabelStyle = new GUIStyle(EditorStyles.boldLabel);
            customLabelStyle.fontSize = 15; // 设置字号大小
            EditorGUILayout.LabelField("● HKTools 框架设置：", customLabelStyle, GUILayout.ExpandWidth(true));
            GUILayout.Space(10);

            if (architectureTypeNames.Length == 0)
            {
                EditorGUILayout.HelpBox("未找到任何继承自 Architecture 的类。", MessageType.Warning);
                return;
            }

            int newSelectedIndex = EditorGUILayout.Popup("当前框架(Architecture)：", selectedIndex, architectureTypeNames);

            if (newSelectedIndex != selectedIndex)
            {
                selectedIndex = newSelectedIndex;
            }

            GUILayout.Space(8);

            if (GUILayout.Button("设置为当前 Architecture"))
            {
                SetCurrentArchitecture();
            }

            EditorGUILayout.Space(2);

            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

            EditorGUILayout.Space(2);

            EditorGUILayout.LabelField("● HKTools 全局设置：", customLabelStyle, GUILayout.ExpandWidth(true));
            GUILayout.Space(10);

            // 遍历工具列表，生成界面元素
            foreach (var tool in tools)
            {
                bool preState = tool.State;
                bool newState = EditorGUILayout.ToggleLeft(tool.DisplayName, preState);

                // 如果用户更改了工具的状态，更新状态
                if (preState != newState)
                {
                    tool.State = newState;
                }

                EditorGUILayout.Space(5);
            }
        }

        void FindAllArchitectureTypes()
        {
            // 获取所有已加载的程序集  
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

            // 定义一个列表来存储找到的类型  
            var typeList = new List<Type>();

            // 遍历所有程序集  
            foreach (var assembly in assemblies)
            {
                // 获取程序集中的所有类型  
                var types = assembly.GetTypes();

                foreach (var type in types)
                {
                    // 检查类型是否继承自 Architecture<>  
                    if (type.IsClass && !type.IsAbstract && InheritsFromGenericType(type, typeof(Architecture<>)))
                    {
                        // 过滤掉 QFramework 命名空间下的类型  
                        if (type.Namespace != null && !type.Namespace.StartsWith("QFramework"))
                        {
                            typeList.Add(type);
                        }
                        else if (type.Namespace == null)
                        {
                            typeList.Add(type);
                        }
                    }
                }
            }

            architectureTypes = typeList.ToArray();
            architectureTypeNames = architectureTypes.Select(t => t.Name).ToArray();
        }

        bool InheritsFromGenericType(Type type, Type genericType)
        {
            while (type != null && type != typeof(object))
            {
                var cur = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
                if (cur == genericType)
                {
                    return true;
                }
                type = type.BaseType;
            }
            return false;
        }

        void SetSelectedIndexToCurrentArchitecture()
        {
            if (!File.Exists(scriptPath))
            {
                // 文件不存在，默认选中第一个  
                selectedIndex = 0;
                return;
            }

            // 读取代码文件内容  
            string codeContents = File.ReadAllText(scriptPath);

            // 构造正则表达式，匹配 architecture = XXX.Interface;  
            string pattern = @"architecture\s*=\s*(?<typeName>[\w\.]+)\.Interface;";

            Match match = Regex.Match(codeContents, pattern);

            if (match.Success)
            {
                string typeNameInCode = match.Groups["typeName"].Value;

                // 遍历 architectureTypes，比较 FullName  
                for (int i = 0; i < architectureTypes.Length; i++)
                {
                    if (architectureTypes[i].FullName == typeNameInCode)
                    {
                        selectedIndex = i;
                        return;
                    }
                }
            }

            // 如果未找到匹配的类型，默认选中第一个  
            selectedIndex = 0;
        }

        void SetCurrentArchitecture()
        {
            Type selectedType = architectureTypes[selectedIndex];

            if (!File.Exists(scriptPath))
            {
                EditorUtility.DisplayDialog("错误", $"未找到文件：{scriptPath}", "确定");
                return;
            }

            // 读取代码文件内容  
            string codeContents = File.ReadAllText(scriptPath);

            // 构造正则表达式，匹配 architecture = XXX.Interface;  
            string pattern = @"architecture\s*=\s*.*?\.Interface;";

            // 构造替换的字符串，始终使用完整类型名  
            string fullTypeName = selectedType.FullName;
            string replacement = $"architecture = {fullTypeName}.Interface;";

            // 不再添加 using 语句  

            // 检查是否匹配需要替换的代码  
            if (!Regex.IsMatch(codeContents, pattern))
            {
                EditorUtility.DisplayDialog("错误", "在文件中未找到需要替换的内容。", "确定");
                return;
            }

            // 进行替换  
            string newCodeContents = Regex.Replace(codeContents, pattern, replacement);

            // 写回修改后的代码内容  
            File.WriteAllText(scriptPath, newCodeContents);

            // 刷新 Unity 资产数据库  
            AssetDatabase.Refresh();

            EditorUtility.DisplayDialog("成功", $"已将 {selectedType.FullName} 设置为当前 Architecture，代码已更新。", "确定");
        }
    }
}